/*
 * Copyright (C) 2005-2011 MaNGOS <http://www.getmangos.com/>
 *
 * Copyright (C) 2008-2011 Trinity <http://www.trinitycore.org/>
 *
 * Copyright (C) 2006-2011 ScriptDev2 <http://www.scriptdev2.com/>
 *
 * Copyright (C) 2010-2011 ProjectSkyfire <http://www.projectskyfire.org/>
 * 
 * Copyright (C) 2011 ArkCORE <http://www.arkania.net/>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/* ScriptData
 SDName: Sholazar_Basin
 SD%Complete: 100
 SDComment: Quest support: 11253, 11241.
 SDCategory: howling_fjord
 EndScriptData */

/* ContentData
 npc_plaguehound_tracker
 npc_apothecary_hanes
 EndContentData */

#include "ScriptPCH.h"
#include "ScriptedEscortAI.h"

/*######
 ## npc_apothecary_hanes
 ######*/
enum Entries {
	NPC_APOTHECARY_HANES = 23784,
	FACTION_ESCORTEE_A = 774,
	FACTION_ESCORTEE_H = 775,
	NPC_HANES_FIRE_TRIGGER = 23968,
	QUEST_TRAIL_OF_FIRE = 11241,
	SPELL_COSMETIC_LOW_POLY_FIRE = 56274
};

class npc_apothecary_hanes: public CreatureScript {
public:
	npc_apothecary_hanes() :
			CreatureScript("npc_apothecary_hanes") {
	}

	bool OnQuestAccept(Player* pPlayer, Creature* pCreature,
			Quest const* quest) {
		if (quest->GetQuestId() == QUEST_TRAIL_OF_FIRE) {
			switch (pPlayer->GetTeam()) {
			case ALLIANCE:
				pCreature->setFaction(FACTION_ESCORTEE_A);
				break;
			case HORDE:
				pCreature->setFaction(FACTION_ESCORTEE_H);
				break;
			}
			CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false,
					pPlayer->GetGUID());
		}
		return true;
	}

	struct npc_Apothecary_HanesAI: public npc_escortAI {
		npc_Apothecary_HanesAI(Creature* pCreature) :
				npc_escortAI(pCreature) {
		}
		uint32 PotTimer;

		void Reset() {
			SetDespawnAtFar(false);
			PotTimer = 10000; //10 sec cooldown on potion
		}

		void JustDied(Unit* /*killer*/) {
			if (Player* pPlayer = GetPlayerForEscort())
				pPlayer->FailQuest(QUEST_TRAIL_OF_FIRE);
		}

		void UpdateEscortAI(const uint32 diff) {
			if (HealthBelowPct(75)) {
				if (PotTimer <= diff) {
					DoCast(me, 17534, true);
					PotTimer = 10000;
				} else
					PotTimer -= diff;
			}
			if (GetAttack() && UpdateVictim())
				DoMeleeAttackIfReady();
		}

		void WaypointReached(uint32 i) {
			Player* pPlayer = GetPlayerForEscort();
			if (!pPlayer)
				return;
			switch (i) {
			case 1:
				me->SetReactState(REACT_AGGRESSIVE);
				SetRun(true);
				break;
			case 23:
				if (pPlayer)
					pPlayer->GroupEventHappens(QUEST_TRAIL_OF_FIRE, me);
				me->ForcedDespawn();
				break;
			case 5:
				if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER, 10.0f))
					Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE,
							false);
				SetRun(false);
				break;
			case 6:
				if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER, 10.0f))
					Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE,
							false);
				SetRun(true);
				break;
			case 8:
				if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER, 10.0f))
					Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE,
							false);
				SetRun(false);
				break;
			case 9:
				if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER, 10.0f))
					Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE,
							false);
				break;
			case 10:
				SetRun(true);
				break;
			case 13:
				SetRun(false);
				break;
			case 14:
				if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER, 10.0f))
					Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE,
							false);
				SetRun(true);
				break;
			}
		}
	};

	CreatureAI *GetAI(Creature *creature) const {
		return new npc_Apothecary_HanesAI(creature);
	}
};

/*######
 ## npc_plaguehound_tracker
 ######*/

enum ePlaguehound {
	QUEST_SNIFF_OUT_ENEMY = 11253
};

class npc_plaguehound_tracker: public CreatureScript {
public:
	npc_plaguehound_tracker() :
			CreatureScript("npc_plaguehound_tracker") {
	}

	struct npc_plaguehound_trackerAI: public npc_escortAI {
		npc_plaguehound_trackerAI(Creature* pCreature) :
				npc_escortAI(pCreature) {
		}

		void Reset() {
			InitScriptData();
		}

		void InitScriptData() {
			Player* pPlayer = NULL;
			if (me->isSummon())
				if (Unit* summoner = CAST_SUM(me)->GetSummoner())
					if (summoner->GetTypeId() == TYPEID_PLAYER)
						pPlayer = CAST_PLR(summoner);

			if (!pPlayer)
				return;

			me->SetUnitMovementFlags(MOVEMENTFLAG_WALKING);
			Start(false, false, pPlayer->GetGUID());
		}

		void WaypointReached(uint32 i) {
			Player* pPlayer = NULL;
			if (me->isSummon())
				if (Unit* summoner = CAST_SUM(me)->GetSummoner())
					if (summoner->GetTypeId() == TYPEID_PLAYER)
						pPlayer = CAST_PLR(summoner);

			if (!pPlayer)
				return;

			switch (i) {
			case 26:
				me->ForcedDespawn();
				break;
			}
		}
	};

	CreatureAI *GetAI(Creature *creature) const {
		return new npc_plaguehound_trackerAI(creature);
	}
};

/*######
 ## npc_razael_and_lyana
 ######*/

#define GOSSIP_RAZAEL_REPORT "High Executor Anselm wants a report on the situation."
#define GOSSIP_LYANA_REPORT "High Executor Anselm requests your report."

enum eRazael {
	QUEST_REPORTS_FROM_THE_FIELD = 11221,
	NPC_RAZAEL = 23998,
	NPC_LYANA = 23778,
	GOSSIP_TEXTID_RAZAEL1 = 11562,
	GOSSIP_TEXTID_RAZAEL2 = 11564,
	GOSSIP_TEXTID_LYANA1 = 11586,
	GOSSIP_TEXTID_LYANA2 = 11588
};

class npc_razael_and_lyana: public CreatureScript {
public:
	npc_razael_and_lyana() :
			CreatureScript("npc_razael_and_lyana") {
	}

	bool OnGossipHello(Player* pPlayer, Creature* pCreature) {
		if (pCreature->isQuestGiver())
			pPlayer->PrepareQuestMenu(pCreature->GetGUID());

		if (pPlayer->GetQuestStatus(QUEST_REPORTS_FROM_THE_FIELD)
				== QUEST_STATUS_INCOMPLETE)
			switch (pCreature->GetEntry()) {
			case NPC_RAZAEL:
				if (!pPlayer->GetReqKillOrCastCurrentCount(
						QUEST_REPORTS_FROM_THE_FIELD, NPC_RAZAEL)) {
					pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_RAZAEL_REPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
					pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RAZAEL1, pCreature->GetGUID());
					return true;
				}
				break;
			case NPC_LYANA:
				if (!pPlayer->GetReqKillOrCastCurrentCount(
						QUEST_REPORTS_FROM_THE_FIELD, NPC_LYANA)) {
					pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LYANA_REPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
					pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LYANA1, pCreature->GetGUID());
					return true;
				}
				break;
			}
		pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
		return true;
	}

	bool OnGossipSelect(Player* pPlayer, Creature* pCreature,
			uint32 /*uiSender*/, uint32 uiAction) {
		pPlayer->PlayerTalkClass->ClearMenus();
		switch (uiAction) {
		case GOSSIP_ACTION_INFO_DEF + 1:
			pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RAZAEL2, pCreature->GetGUID());
			pPlayer->TalkedToCreature(NPC_RAZAEL, pCreature->GetGUID());
			break;
		case GOSSIP_ACTION_INFO_DEF + 2:
			pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LYANA2, pCreature->GetGUID());
			pPlayer->TalkedToCreature(NPC_LYANA, pCreature->GetGUID());
			break;
		}
		return true;
	}
};

/*######
 ## npc_mcgoyver
 ######*/

#define GOSSIP_ITEM_MG_I  "Walt sent me to pick up some dark iron ingots."
#define GOSSIP_ITEM_MG_II "Yarp."

enum eMcGoyver {
	QUEST_WE_CAN_REBUILD_IT = 11483,

	SPELL_CREATURE_DARK_IRON_INGOTS = 44512,
	SPELL_TAXI_EXPLORERS_LEAGUE = 44280,

	GOSSIP_TEXTID_MCGOYVER = 12193
};

class npc_mcgoyver: public CreatureScript {
public:
	npc_mcgoyver() :
			CreatureScript("npc_mcgoyver") {
	}

	bool OnGossipHello(Player* pPlayer, Creature* pCreature) {
		if (pPlayer->GetQuestStatus(QUEST_WE_CAN_REBUILD_IT)
				== QUEST_STATUS_INCOMPLETE)
			pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MG_I, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);

		pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
		return true;
	}

	bool OnGossipSelect(Player* pPlayer, Creature* pCreature,
			uint32 /*uiSender*/, uint32 uiAction) {
		pPlayer->PlayerTalkClass->ClearMenus();
		switch (uiAction) {
		case GOSSIP_ACTION_INFO_DEF + 1:
			pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MG_II, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
			pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_MCGOYVER, pCreature->GetGUID());
			pPlayer->CastSpell(pPlayer, SPELL_CREATURE_DARK_IRON_INGOTS, true);
			break;
		case GOSSIP_ACTION_INFO_DEF + 2:
			pPlayer->CastSpell(pPlayer, SPELL_TAXI_EXPLORERS_LEAGUE, true);
			pPlayer->CLOSE_GOSSIP_MENU();
			break;
		}
		return true;
	}
};

/*######
 ## npc_daegarn
 ######*/

enum eDaegarnn {
	QUEST_DEFEAT_AT_RING = 11300,

	NPC_FIRJUS = 24213,
	NPC_JLARBORN = 24215,
	NPC_YOROS = 24214,
	NPC_OLUF = 23931,

	NPC_PRISONER_1 = 24253, // looks the same but has different abilities
	NPC_PRISONER_2 = 24254,
	NPC_PRISONER_3 = 24255,
};

static float afSummon[] = { 838.81f, -4678.06f, -94.182f };
static float afCenter[] = { 801.88f, -4721.87f, -96.143f };

class npc_daegarn: public CreatureScript {
public:
	npc_daegarn() :
			CreatureScript("npc_daegarn") {
	}

	bool OnQuestAccept(Player* pPlayer, Creature* pCreature,
			const Quest* pQuest) {
		if (pQuest->GetQuestId() == QUEST_DEFEAT_AT_RING) {
			if (npc_daegarnAI* pDaegarnAI = CAST_AI(npc_daegarn::npc_daegarnAI, pCreature->AI()))
				pDaegarnAI->StartEvent(pPlayer->GetGUID());
		}

		return true;
	}

	// TODO: make prisoners help (unclear if summoned or using npc's from surrounding cages (summon inside small cages?))
	struct npc_daegarnAI: public ScriptedAI {
		npc_daegarnAI(Creature *pCreature) :
				ScriptedAI(pCreature) {
		}

		bool bEventInProgress;
		uint64 uiPlayerGUID;

		void Reset() {
			bEventInProgress = false;
			uiPlayerGUID = 0;
		}

		void StartEvent(uint64 uiGUID) {
			if (bEventInProgress)
				return;

			uiPlayerGUID = uiGUID;

			SummonGladiator(NPC_FIRJUS);
		}

		void JustSummoned(Creature* pSummon) {
			if (Player* pPlayer = me->GetPlayer(*me, uiPlayerGUID)) {
				if (pPlayer->isAlive()) {
					pSummon->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
					pSummon->GetMotionMaster()->MovePoint(0, afCenter[0],
							afCenter[1], afCenter[2]);
					pSummon->AI()->AttackStart(pPlayer);
					return;
				}
			}

			Reset();
		}

		void SummonGladiator(uint32 uiEntry) {
			me->SummonCreature(uiEntry, afSummon[0], afSummon[1], afSummon[2],
					0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,
					30 * IN_MILLISECONDS);
		}

		void SummonedCreatureDies(Creature* pSummoned, Unit* pKiller) {
			uint32 uiEntry = 0;

			// will eventually reset the event if something goes wrong
			switch (pSummoned->GetEntry()) {
			case NPC_FIRJUS:
				uiEntry = NPC_JLARBORN;
				break;
			case NPC_JLARBORN:
				uiEntry = NPC_YOROS;
				break;
			case NPC_YOROS:
				uiEntry = NPC_OLUF;
				break;
			case NPC_OLUF:
				Reset();
				return;
			}

			SummonGladiator(uiEntry);
		}
	};

	CreatureAI *GetAI(Creature *creature) const {
		return new npc_daegarnAI(creature);
	}
};

void AddSC_howling_fjord() {
	new npc_apothecary_hanes;
	new npc_plaguehound_tracker;
	new npc_razael_and_lyana;
	new npc_mcgoyver;
	new npc_daegarn;
}
